package com.numberone.iotplatform.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.numberone.iotplatform.dto.a_i_box.*;
import com.numberone.iotplatform.service.AiBoxApiService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * AiBoxApiService 的 HTTP RestTemplate 实现。
 * 【未来】可以被 WebSocket 或其他协议的实现类替换。
 * 所有代码已确认兼容 JDK 1.8。
 */
@Service
public class AiBoxApiServiceImpl implements AiBoxApiService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 登录到 AI BOX 设备。
     * 对应 API 文档 1.1 登录
     */
    @Override
    public boolean login(String ip, int port, String username, String password) {
        String loginUrl = String.format("http://%s:%d/api/system/user/login", ip, port);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        Map<String, String> body = new HashMap<>();
        body.put("username", username);
        body.put("password", password);
        HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(body, headers);

        try {
            ResponseEntity<JsonNode> response = restTemplate.postForEntity(loginUrl, requestEntity, JsonNode.class);

            // 根据 API 文档，code 为 0 代表成功
            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                return response.getBody().get("code").asInt() == 0;
            }
        } catch (Exception e) {
            // 捕获所有异常 (如连接超时, 401等)，均视为登录失败
            System.err.printf("Failed to login to AI BOX at %s:%d. Reason: %s\n", ip, port, e.getMessage());
        }
        return false;
    }

    @Override
    public boolean logout(String ip, int port) {
        return false;
    }

    /**
     * 重启设备。
     * 对应 API 文档 2.1.1 重启设备
     */
    @Override
    public boolean rebootDevice(String ip, int port) {
        String url = String.format("http://%s:%d/api/system/reboot", ip, port);
        try {
            // 重启是 PUT 请求，且没有请求体
            ResponseEntity<JsonNode> response = restTemplate.exchange(url, HttpMethod.PUT, null, JsonNode.class);

            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                return response.getBody().get("code").asInt() == 0;
            }
        } catch (Exception e) {
            System.err.printf("Failed to reboot device at %s:%d. Reason: %s\n", ip, port, e.getMessage());
        }
        return false;
    }

    @Override
    public boolean upgradeFirmware(String ip, int port, FirmwareUpgradeDTO firmware) {
        return false;
    }

    @Override
    public Optional<NetworkInfoDTO> getNetworkInfo(String ip, int port) {
        return Optional.empty();
    }

    @Override
    public boolean setNetworkInfo(String ip, int port, NetworkInfoDTO networkInfo) {
        return false;
    }

    @Override
    public Optional<TimeInfoDTO> getTimeInfo(String ip, int port) {
        return Optional.empty();
    }

    @Override
    public boolean setTimeInfo(String ip, int port, TimeInfoDTO timeInfo) {
        return false;
    }

    @Override
    public boolean setWebServerMode(String ip, int port, WebServerModeDTO mode) {
        return false;
    }

    /**
     * 获取设备信息 (版本号, SN等)。
     * 对应 API 文档 2.2.6 获取设备信息
     */
    @Override
    public Optional<DeviceInfoDTO> getDeviceInfo(String ip, int port) {
        String url = String.format("http://%s:%d/api/device", ip, port);
        try {
            ResponseEntity<JsonNode> response = restTemplate.getForEntity(url, JsonNode.class);

            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null && response.getBody().get("code").asInt() == 0) {
                JsonNode dataNode = response.getBody().get("data");
                // 使用 ObjectMapper 将 data 节点转换为我们的 DTO
                DeviceInfoDTO deviceInfo = objectMapper.treeToValue(dataNode, DeviceInfoDTO.class);
                return Optional.of(deviceInfo);
            }
        } catch (Exception e) {
            System.err.printf("Failed to get device info from %s:%d. Reason: %s\n", ip, port, e.getMessage());
        }
        return Optional.empty();
    }



    @Override
    public Optional<AddChannelResponseDTO> addChannelManually(String ip, int port, ChannelDTO channelConfig) {
        return Optional.empty();
    }

    @Override
    public Optional<OnvifDiscoveryResultDTO> discoverOnvifDevices(String ip, int port) {
        return Optional.empty();
    }

    @Override
    public Optional<AddChannelResponseDTO> addChannelAutomatically(String ip, int port, OnvifChannelDTO channelConfig) {
        return Optional.empty();
    }

    @Override
    public boolean deleteChannel(String ip, int port, int channelId) {
        return false;
    }

    @Override
    public boolean updateChannel(String ip, int port, ChannelUpdateDTO channelUpdate) {
        return false;
    }

    @Override
    public Optional<List<ChannelInfoDTO>> getChannels(String ip, int port) {
        return Optional.empty();
    }

    @Override
    public Optional<String> getChannelSnapshot(String ip, int port, int videoNo) {
        return Optional.empty();
    }

    @Override
    public boolean setChannelMode(String ip, int port, ChannelModeDTO channelMode) {
        return false;
    }

    @Override
    public boolean setFtpUploadConfig(String ip, int port, FtpConfigDTO ftpConfig) {
        return false;
    }

    @Override
    public Optional<FtpConfigDTO> getFtpUploadConfig(String ip, int port) {
        return Optional.empty();
    }

    @Override
    public boolean testFtpConnection(String ip, int port, FtpTestDTO ftpTest) {
        return false;
    }

    @Override
    public boolean setWsReportsConfig(String ip, int port, WsReportConfigDTO wsConfig) {
        return false;
    }

    @Override
    public Optional<WsReportConfigDTO> getWsReportsConfig(String ip, int port) {
        return Optional.empty();
    }

    @Override
    public boolean setHttpReportsConfig(String ip, int port, HttpReportConfigDTO httpConfig) {
        return false;
    }

    @Override
    public Optional<HttpReportConfigDTO> getHttpReportsConfig(String ip, int port) {
        return Optional.empty();
    }

    @Override
    public Optional<FaceAddResponseDTO> addFace(String ip, int port, FaceAddRequestDTO faceData) {
        return Optional.empty();
    }

    @Override
    public Optional<FaceListResponseDTO> listAllFaces(String ip, int port, int pageOffset, int pageSize) {
        return Optional.empty();
    }

    @Override
    public boolean deleteFace(String ip, int port, String faceToken) {
        return false;
    }

    @Override
    public boolean deleteFaceImage(String ip, int port, String imageId) {
        return false;
    }

    @Override
    public Optional<FaceDetailDTO> getFaceDetail(String ip, int port, String faceToken) {
        return Optional.empty();
    }

    @Override
    public Optional<OriginalImageDTO> getOriginalImage(String ip, int port, String imageId) {
        return Optional.empty();
    }

    @Override
    public boolean initializeFaceLibrary(String ip, int port) {
        return false;
    }

    @Override
    public Optional<List<FaceGroupDTO>> listFaceGroups(String ip, int port) {
        return Optional.empty();
    }

    @Override
    public boolean createFaceGroup(String ip, int port, FaceGroupDTO groupData) {
        return false;
    }

    @Override
    public boolean deleteFaceGroup(String ip, int port, String groupId, int deleteAllFace) {
        return false;
    }

    @Override
    public Optional<FaceListInGroupDTO> listFacesInGroup(String ip, int port, String groupId, int pageOffset, int pageSize) {
        return Optional.empty();
    }

    @Override
    public Optional<BindingResponseDTO> bindFaceToGroups(String ip, int port, String faceToken, List<String> groupIds) {
        return Optional.empty();
    }

    @Override
    public Optional<BindingResponseDTO> unbindFaceFromGroups(String ip, int port, String faceToken, List<String> groupIds) {
        return Optional.empty();
    }

    @Override
    public boolean updateFaceGroup(String ip, int port, FaceGroupUpdateDTO groupData) {
        return false;
    }

    @Override
    public Optional<FaceCompareResponseDTO> compareFaces1v1(String ip, int port, FaceCompareRequestDTO compareData) {
        return Optional.empty();
    }

    @Override
    public Optional<FaceSearchResponseDTO> searchFace1vN(String ip, int port, FaceSearchRequestDTO searchData) {
        return Optional.empty();
    }

    @Override
    public Optional<BindingResponseDTO> bindVideoToGroups(String ip, int port, int videoNo, List<String> groupIds) {
        return Optional.empty();
    }

    @Override
    public boolean setAlertRules(String ip, int port, int videoNo, AlertRuleConfigDTO ruleConfig) {
        return false;
    }

    @Override
    public Optional<CaptureDTO> pollCapture(String ip, int port) {
        return Optional.empty();
    }

    @Override
    public Optional<AlertDTO> pollAlerts(String ip, int port) {
        return Optional.empty();
    }

    @Override
    public Optional<CaptureQueryResultDTO> queryCaptures(String ip, int port, CaptureQueryDTO query) {
        return Optional.empty();
    }

    @Override
    public Optional<RoiAreaDTO> getRoiArea(String ip, int port, int videoNo) {
        return Optional.empty();
    }

    @Override
    public boolean setRoiArea(String ip, int port, int videoNo, RoiAreaDTO roiArea) {
        return false;
    }

    @Override
    public Optional<DetectLineDTO> getDetectLine(String ip, int port, int videoNo) {
        return Optional.empty();
    }

    @Override
    public boolean setDetectLine(String ip, int port, int videoNo, DetectLineDTO detectLine) {
        return false;
    }

    @Override
    public Optional<FaceFeatureResponseDTO> getFaceFeature(String ip, int port, FaceFeatureRequestDTO featureRequest) {
        return Optional.empty();
    }
}